package sk.tuke.kephera.gui;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Arrays;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import sk.tuke.kephera.connector.KepheraConnector;
import sk.tuke.kephera.connector.KepheraMsg;
import sk.tuke.kephera.connector.KepheraUtils;
import sk.tuke.kephera.observer.Observer;

public class GuiMain implements Runnable {
    private static final String LOCAL_PC_NAME = "mar@PC";
    private static final int MOVE_SPEED = 75000;
    private static final int GRIP_SPEED = 75;
    private static KepheraConnector kpc;
    private volatile int ramenoState = 0;
    private JPanel panel;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new GuiMain());
    }

    @Override
    public void run() {
        createAndShowGUI();
    }

    @Override
    protected void finalize() throws Throwable {
        kpc.disconnect();
        super.finalize();
    }

    private void createAndShowGUI() {
        kpc = KepheraConnector.createUdpListeningConnector(LOCAL_PC_NAME, "255.255.255.255", 5002);
        kpc.connect();

        kpc.addObserver(new Observer<KepheraMsg>() {
            @Override
            public void handle(KepheraMsg msg) {
                if (msg.getFrom().contains("gripper")) {
                    System.out.println("###############################");
                    System.out.println("GRIPPER SI CHCI ULOZIT DO DB :]");
                    System.out.println(KepheraUtils.toJson(msg));
                }
            }
        });
        KepheraMsg createDotaz = createDotaz("gripper@3", "rameno", ramenoState);
        System.out.println("pred poslanim");
        kpc.send(createDotaz);
        System.out.println("pred prijmem");
        kpc.receive(createDotaz.getType(), 3000);
        System.out.println("po prijmu");

        JFrame frame = new JFrame("Hello world frame"); // okno
        frame.add(createLayoutPanel());
        frame.pack();
        frame.setLocation(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true); // zobraz okno
    }

    private void send(KepheraMsg createDotaz) {
        kpc.send(createDotaz);
        kpc.receive(createDotaz.getType());
    }

    private Component createLayoutPanel() {
        panel = new JPanel();
        panel.setLayout(new GridLayout(0, 3)); // nedefinovany pocet radku, 2 sloupce

        JPanel movePanel = new JPanel();
        movePanel.setLayout(new GridLayout(0, 2));
        movePanel.add(createButton("forward", KeyEvent.VK_UP, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("kolesa@3", "dolava", MOVE_SPEED));
                System.out.println("vpred");
            }

        }));
        movePanel.add(createButton("backward", KeyEvent.VK_DOWN, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("kolesa@3", "doprava", MOVE_SPEED));
                System.out.println("backward");
            }
        }));
        movePanel.add(createButton("left", KeyEvent.VK_LEFT, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("kolesa@3", "dopredu", MOVE_SPEED));
                System.out.println("left");
            }
        }));
        movePanel.add(createButton("right", KeyEvent.VK_RIGHT, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("kolesa@3", "dozadu", MOVE_SPEED));
                System.out.println("right");
            }
        }));
        movePanel.add(new JLabel("Kolesa"));

        JPanel gripperPanel = new JPanel();
        gripperPanel.setLayout(new GridLayout(0, 2));
        //UP
        gripperPanel.add(createButton("up", KeyEvent.VK_NUMPAD8, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                setRamenoState(ramenoState - GRIP_SPEED);
                send(createDotaz("gripper@3", "rameno", ramenoState));
                System.out.println("up" + ramenoState);
            }
        }));
        //DOWN
        gripperPanel.add(createButton("down", KeyEvent.VK_NUMPAD2, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                setRamenoState(ramenoState + GRIP_SPEED);
                send(createDotaz("gripper@3", "rameno", ramenoState));
                System.out.println("down " + ramenoState);
            }
        }));
        // PUT
        gripperPanel.add(createButton("put", KeyEvent.VK_NUMPAD4, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("gripper@3", "gripper", 0));
                System.out.println("put");
            }
        }));
        //LEAVE
        gripperPanel.add(createButton("leave", KeyEvent.VK_NUMPAD6, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                send(createDotaz("gripper@3", "gripper", 1000));
                System.out.println("leave");
            }
        }));
        gripperPanel.add(new JLabel("Gripper"));

        panel.add(movePanel);
        panel.add(gripperPanel);
        return panel;
    }

    private JButton createButton(String name, int key, final ActionListener l) {
        JButton jButton = new JButton(name);
        jButton.addActionListener(l);

        //pridat i volani na klavesnici
        InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
        ActionMap am = panel.getActionMap();

        char chkey = (char) key;
        im.put(KeyStroke.getKeyStroke( chkey, 0), chkey);
        am.put(chkey, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                l.actionPerformed(e);
            }
        });

        return jButton;
    }

    private static KepheraMsg createDotaz(String to, String program, int value) {
        return createDotaz(to, program, String.valueOf(value));
    }

    private static KepheraMsg createDotaz(String to, String program, String value) {
        KepheraMsg d = new KepheraMsg();
//        d.setType((int) (Math.random() * 50000)); //auto increment
        System.out.println(d.getType());
        d.setFrom(LOCAL_PC_NAME);
        d.setTo(Arrays.asList(to));
        d.getBody().put(program, value);
        return d;
    }

    public void setRamenoState(int ramenoState) {
        this.ramenoState = Math.min(Math.max(0, ramenoState), 1000);
    }

}
